﻿using System;
using System.Web;

using Job.Core.Security;

namespace Job.Core.Web
{
    /// <summary>
    /// cookie 辅助管理封装。
    /// </summary>
    public static class Cookie
    {
        #region Methods

        /// <summary>
        /// 获取 cookie 值。
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        /// <param name="defaultValue">cookie 不存在时返回的默认值。</param>
        /// <param name="decryptKey">如果是为一个加密 cookie，请输入原始加密 key。</param>
        /// <returns>获取到的 cookie 值，不存在是则返回指定 defaultValue 值。</returns>
        public static string Get(string name, string defaultValue, string decryptKey)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            string result = defaultValue;

            if (HttpContext.Current.Request.Cookies[name] != null)
            {
                result = HttpContext.Current.Request.Cookies[name].Value;

                if (!string.IsNullOrEmpty(decryptKey))
                {
                    Aes aes = new Aes(HttpContext.Current.Request.UserAgent, decryptKey);

                    try
                    {
                        result = aes.Decrypt(result);
                    }
                    catch
                    {
                        result = string.Empty;
                    }
                }
                else
                {
                    result = HttpUtility.UrlDecode(result);
                }               
            }           
           
            return result;
        }

        /// <summary>
        /// 读取 cookie
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        /// <returns>获取到的 cookie 值，不存在指定 cookie 时返回 null。</returns>
        public static string Get(string name)
        {
            return Get(name, string.Empty, null);
        }

        /// <summary>
        /// 设置 cookie。
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        /// <param name="value">cookie 值。</param>
        /// <param name="expiresValue">过期值。</param>
        /// <param name="expiresType">过期方式。</param>
        /// <param name="decryptKey">加密 key。</param>
        /// <param name="domain">域(可不设置)。</param>
        public static void Set(string name, string value, int expiresValue, CookieExpiresType expiresType, string decryptKey, string domain)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            HttpCookie cookie = new HttpCookie(name);

            if (!string.IsNullOrEmpty(decryptKey))
            {
                Aes aes = new Aes(HttpContext.Current.Request.UserAgent, decryptKey);
                value = aes.Encrypt(value);
                cookie.HttpOnly = true;
                cookie.Value = value;
            }
            else
            {
                if (!string.IsNullOrEmpty(value)) cookie.Value = HttpUtility.ParseQueryString(value).ToString();
            }

            if (!string.IsNullOrEmpty(domain)) cookie.Domain = domain;

            switch (expiresType)
            {
                case CookieExpiresType.Minutes:
                    cookie.Expires = DateTime.Now.AddMinutes(expiresValue);
                    break;
                case CookieExpiresType.Hours:
                    cookie.Expires = DateTime.Now.AddHours(expiresValue);
                    break;
                case CookieExpiresType.Days:
                    cookie.Expires = DateTime.Now.AddDays(expiresValue);
                    break;
                case CookieExpiresType.Months:
                    cookie.Expires = DateTime.Now.AddMonths(expiresValue);
                    break;
                case CookieExpiresType.Years:
                    cookie.Expires = DateTime.Now.AddYears(expiresValue);
                    break;
                case CookieExpiresType.OnlyBrowse:
                default:
                    break;
            }

            HttpContext.Current.Response.Cookies.Remove(name);
            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        /// <summary>
        /// 设置 cookie。
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        /// <param name="value">cookie 值。</param>
        /// <param name="expiresValue">过期值。</param>
        /// <param name="expiresType">过期方式。</param>
        public static void Set(string name, string value, int expiresValue, CookieExpiresType expiresType)
        {
            Set(name, value, expiresValue, expiresType, null, null);
        }

        /// <summary>
        /// 设置 cookie。
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        /// <param name="value">cookie 值。</param>
        public static void Set(string name, string value)
        {
            Set(name, value, 0, CookieExpiresType.OnlyBrowse);
        }

        /// <summary>
        /// 移除一个 cookie。
        /// </summary>
        /// <param name="name">cookie 名称。</param>
        public static void Remove(string name)
        {
            Set(name, string.Empty, -1, CookieExpiresType.Minutes);
        }

        /// <summary>
        /// 移除一个 cookie。
        /// </summary>
        /// <param name="cookie">cookie 对象。</param>
        public static void Remove(HttpCookie cookie)
        {
            Remove(cookie.Name);
        }

        /// <summary>
        /// 清除所有 cookie。
        /// </summary>
        public static void Clear()
        {
            HttpCookieCollection hcc = HttpContext.Current.Request.Cookies;
            for (int i = 0, j = hcc.Count; i < j; i++)
            {
                Remove(hcc[i]);
            }
        }
        #endregion
    }

    #region CookieExpiresType

    /// <summary>
    /// cookie 过期时间单位。
    /// </summary>
    public enum CookieExpiresType
    {
        /// <summary>
        /// 分钟。
        /// </summary>
        Minutes,

        /// <summary>
        /// 小时。
        /// </summary>
        Hours,

        /// <summary>
        /// 天。
        /// </summary>
        Days,

        /// <summary>
        /// 月。
        /// </summary>
        Months,

        /// <summary>
        /// 年。
        /// </summary>
        Years,

        /// <summary>
        /// 仅浏览器进程，当设置为此值时将忽略前面的expiry参数。
        /// </summary>
        OnlyBrowse
    }

    #endregion
}